import { Box, Flex, IconButton, useDisclosure } from "@chakra-ui/react";
import React, { useCallback, useContext, useMemo, useState } from "react";
import 'reactflow/dist/style.css';
import { customAlphabet } from 'nanoid';

import ReactFlow, {
  Background,
  Connection,
  Controls,
  ControlButton,
  MiniMap,
  NodeProps,
  ReactFlowProvider,
  useReactFlow,
  NodeChange,
  OnConnectStartParams,
  addEdge,
  EdgeChange,
  Edge,
  applyNodeChanges,
  applyEdgeChanges,
} from "reactflow";

import "reactflow/dist/style.css";
import { FlowNodeTypeEnum } from "../node/constant";
import dynamic from "next/dynamic";
import { WorkflowContext } from "@/context/WorkflowContext";
import { EDGE_TYPE } from "@/enums/AppTypeEnum";
import { useToast } from "@/components/hooks/useToast";
import { connectionLineStyle, defaultEdgeOptions } from "./constants";
import { ButtonEdge } from "./components/ButtonEdge";
import NodeTemplatesModal from "./NodeTemplatesModal";

const storeNode2FlowNode = (storeNode: any) => {
  // replace item data
  const moduleItem: any = {
    ...storeNode,
    avatar: storeNode?.avatar,
    inputs: storeNode.inputs
      .map((storeInput: any) => {
        return {
          ...storeInput
        };
      }),
    outputs: storeNode.outputs.map((storeOutput: any) => {
      return {
        ...storeOutput,
        value: storeOutput.value
      };
    }),
    version: storeNode.version || '481'
  };
  return {
    id: storeNode.nodeId,
    type: storeNode.flowNodeType,
    data: moduleItem,
    position: storeNode.position || { x: 0, y: 0 }
  };
};

export const getNanoid = (size = 12) => {
  const firstChar = customAlphabet('abcdefghijklmnopqrstuvwxyz', 1)();

  if (size === 1) return firstChar;

  const randomsStr = customAlphabet(
    'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890',
    size - 1
  )();

  return `${firstChar}${randomsStr}`;
};



export const storeEdgesRenderEdge = ({ edge }: { edge: any }) => {
  return {
    ...edge,
    id: getNanoid(),
    type: 'default'
  };
};

const edgeTypes = {
  [EDGE_TYPE]: ButtonEdge
};


const nodeTypes: Record<any, any> = {
  [FlowNodeTypeEnum.systemConfig]: dynamic(() => import('./nodes/NodeSystemConfig')),
  [FlowNodeTypeEnum.workflowStart]: dynamic(() => import('./nodes/NodeWorkflowStart')),
  [FlowNodeTypeEnum.answerNode]: dynamic(() => import('./nodes/NodeAnswer'))
}

const Container = React.memo(function Container() {
  const { nodes, edges, setEdges, onNodesChange, onEdgesChange,reactFlowWrapper } = useContext(WorkflowContext)
  // console.log(workflow,'workflow')

  const { toast } = useToast();


  const {
    isOpen: isOpenTemplate,
    onOpen: onOpenTemplate,
    onClose: onCloseTemplate
  } = useDisclosure();



  // const onNodesChange = useCallback(
  //   (changes: NodeChange[]) => setNodes((nds) => applyNodeChanges(changes, nds)),
  //   []
  // );
  // const onEdgesChange = useCallback(
  //   (changes: EdgeChange[]) => setEdges((eds) => applyEdgeChanges(changes, eds)),
  //   []
  // );
  // const onNodesChange = ()=>{
  //     console.log('onNodesChange')
  // }

  // const onEdgesChange = ()=>{
  //   console.log('onEdgesChange')
  // }

  const customOnConnect = useCallback(
    (connect: any) => {
      console.log(connect)
      if (connect.source === connect.target) {
        return toast({
          status: 'warning',
          title: ('core.module.Can not connect self')
        });
      }
      onConnect({ connect })
    },
    []
  )

  const onConnect = useCallback(
    ({ connect }: { connect: Connection }) => {
      setEdges((state:any) =>
        addEdge(
          {
            ...connect,
            type: EDGE_TYPE
          },
          state
        )
      );
    },
    [setEdges]
  );

  return (
    <ReactFlowProvider>
     <Box className="flex w-full flex-1 relative" style={{ position: 'relative' }}>
   
      <ReactFlow
        ref={reactFlowWrapper}
        defaultEdgeOptions={defaultEdgeOptions}
        connectionLineStyle={connectionLineStyle}
        nodes={nodes}
        onNodesChange={onNodesChange}
        edges={edges}
        minZoom={0.1}
        maxZoom={1.5}
        // edgeTypes={edgeTypes}
        elevateEdgesOnSelect
        onConnect={customOnConnect}
        nodeTypes={nodeTypes}
        onEdgesChange={onEdgesChange}
        fitView
      >
        <MiniMap
          style={{
            height: 78,
            width: 126,
            marginBottom: 35
          }}
          pannable
        />
        <Background />
        <Controls />
      </ReactFlow>

      <>
       <NodeTemplatesModal isOpen={isOpenTemplate} onClose={onCloseTemplate} />
        <IconButton
          zIndex={1}
          boxShadow={'2px 2px 6px #85b1ff'}
            size={'mdSquare'}
            borderRadius={'50%'}
            position={'absolute'}
            top={5}
            left={0}
            onClick={() => {
              isOpenTemplate ? onCloseTemplate() : onOpenTemplate();
            }}
            >
        </IconButton>
       </>
    </Box>
    </ReactFlowProvider>
  );
});

// const memoRenderContainer = useMemo(() => {
//     const {
//         isOpen: isOpenTemplate,
//         onOpen: onOpenTemplate,
//         onClose: onCloseTemplate
//       } = useDisclosure();

// })

// const Flow = ()=>{
//     return (
//         <Box h={'100%'} position={'fixed'} zIndex={999} top={0} left={0} right={0} bottom={0}>
//           <ReactFlowProvider>
//             <Flex h={'100%'} flexDirection={'column'} bg={'myGray.50'}>
//               {memoRenderContainer}
//             </Flex>
//           </ReactFlowProvider>
//         </Box>
//       );
// }

const Flow = Container;

export default Flow;
